from django.shortcuts import render, HttpResponse
from threading import Thread
# Create your views here.
from utils.common_logger import logger
from rest_framework.views import APIView
from rest_framework.response import Response
from django_redis import get_redis_connection

class InsertDataToRedis(APIView):
    throttle_classes = []
    def post(self, request, format=None):
        # 从请求中获取要插入的数据
        data = request.data.get('yzk')
        print(data)

        # 连接到Redis数据库
        redis_conn = get_redis_connection("default")  # 使用Django默认Redis连接

        # 将数据插入到Redis中，这里以字符串类型保存
        redis_conn.set("example_key", data)

        return Response({'status': 'success', 'message': 'Data inserted into Redis successfully.'})



### 日志测试
def index(request):
    # DEBUG < INFO < WARNING < ERROR < CRITICAL
    logger.debug('debug级别')
    logger.info('info级别')
    logger.warning('warning级别')
    logger.error('error级别')
    logger.critical('CRITICAL级别')
    a = [1, 2, 3]
    print('asdasd')
    print('111')
    b = a[9]
    print(b)
    # 以后想用print的位置，都用logger.info,以后项目上线，
    # 调高日志输出级别，虽然代码中写了日志输出，实际上并不会输出
    return HttpResponse('ok')


### 全局异常测试
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.exceptions import APIException, ValidationError


class ExceptionTestView(APIView):
    def get(self, request):
        # django异常
        # raise Exception('django异常')

        #
        a = [9, 38, 3]
        print(a[99])
        ## drf 异常
        # raise APIException('drf异常')
        # raise ValidationError('认证失败')
        return Response('ok')


#### 测试自己封装的响应对象
from utils.common_response import APIResponse


class MyResponseView(APIView):
    def get(self, request):
        return APIResponse(result=[{'name': 'lqz', 'price': 19}])


from user.models import User
from rest_framework.viewsets import ViewSet, GenericViewSet
from rest_framework.decorators import action
from rest_framework.exceptions import APIException
from user.serializer import LoginUserSerializer, LoginUserSMSSerializer, UserRegisterSerializer, UserSmsRegisterSerializer
from libs.send_jd_sms import get_code, send_sms_by_mobile
from django.core.cache import cache
# from celery_task.user_task import send_sms
from rest_framework.mixins import CreateModelMixin,ListModelMixin
from user.models import User

class UserView(GenericViewSet, CreateModelMixin,ListModelMixin):
    serializer_class = LoginUserSerializer
    queryset = User.objects.all()

    # ********************************手机号码验证和发送验证码

    # 验证手机号是否存在接口---》get请求---》跟数据库有关系，但不需要序列化----》自动生成路由
    @action(methods=['GET'], detail=False)
    def check_mobile(self, request, *args, **kwargs):
        mobile = request.query_params.get('mobile', None)
        if mobile:
            user = User.objects.filter(mobile=mobile).first()
            if user:
                return APIResponse(msg='手机号存在')
        raise APIException('手机号不存在')

    # 发送短信
    @action(methods=['GET'], detail=False)
    def send_sms(self, request, *args, **kwargs):
        # 前端需要把要发送的手机号传入在地址栏中
        mobile = request.query_params.get('mobile', None)
        code = get_code()  # 把code存起来，放在缓存中
        cache.set('send_sms_code_%s' % mobile, code)
        # 从缓存中取
        # cache.get('send_sms_code_%s' % mobile)

        if mobile:
            # 开启一个线程，执行发送短信
            # t = Thread(target=send_sms_by_mobile, args=[mobile, code])
            # t.start()
            # 提交异步任务---》异步发送
            res = send_sms.delay(mobile, code)
            print(res)
            return APIResponse(msg='短信已经发送')
        raise APIException('手机号没有携带！')

    # ******************************************登录功能***************************
    # 判断登录方式用哪个序列化类
    def get_serializer_class(self):
        if self.action == 'sms_login':
            return LoginUserSMSSerializer
        elif self.action == 'register' or self.action == 'create':
            return UserRegisterSerializer
        elif self.action == 'sms_register':
            return UserSmsRegisterSerializer
        else:
            # return super().get_serializer_class()
            return self.serializer_class

    # 多方式登录接口---->要不要序列化类----->要序列化类----->继承的视图类基类
    # post请求 ------->前端携带的数据
    @action(methods=['POST'], detail=False)
    def mul_login(self, request, *args, **kwargs):
        # # 校验逻辑要写在序列化类中
        # ser = self.get_serializer(data=request.data)
        # # 只要执行它，就会执行字段自己的校验规则，局部钩子，全局钩子，全局钩子（全局钩子中写验证逻辑，生成token的逻辑）
        # ser.is_valid(raise_exception=True)  # 如果校验失败，异常会抛出
        # username = ser.context.get('username')
        # token = ser.context.get('token')
        # icon = ser.context.get('icon')
        # return APIResponse(username=username,token=token,icon=icon)
        return self._common_login(request, *args, **kwargs)

    @action(methods=['POST'], detail=False)
    def sms_login(self, request, *args, **kwargs):
        # 前端传入的格式 {mobile:11111,code:8888}
        # 逻辑在序列化类里面
        return self._common_login(request, *args, **kwargs)

    # 两个登录方式的公共部分
    def _common_login(self, request, *args, **kwargs):
        # 校验逻辑要写在序列化类中
        ser = self.get_serializer(data=request.data)
        # 只要执行它，就会执行字段自己的校验规则，局部钩子，全局钩子，全局钩子（全局钩子中写验证逻辑，生成token的逻辑）
        ser.is_valid(raise_exception=True)  # 如果校验失败，异常会抛出
        username = ser.context.get('username')
        token = ser.context.get('token')
        icon = ser.context.get('icon')
        return APIResponse(username=username, token=token, icon=icon)

    # ************************************注册功能***************************

    # 方式一
    # 自己写的 访问 127.0.0.1：8000/api/v1/user/userinfo/register/   --->post请求即可
    @action(methods=['POST'], detail=False)
    def register(self, request, *args, **kwargs):
        ser = self.get_serializer(data=request.data)
        ser.is_valid(raise_exception=True)
        ser.save()
        # super().create(request,*args,**kwargs)  # 只要这样写，又会走序列化类
        return APIResponse(mag='注册成功')

    def list(self,request,*args,**kwargs):
        print(request.query_params['name'])
        super().list(request,*args, **kwargs)
        return APIResponse(msg='111')

    @action(methods=['GET'], detail=True)
    def send_sms(self, request, pk):
        print(pk)
        # 手机号，从哪去，假设get请求，携带了参数
        phone = request.query_params.get('phone')
        print('发送成功,%s' % phone)
        return Response({'code': 100, 'msg': '发送成功'})
    # 方式二
    # 不自己写了,只要继承CreateModelMixin，访问：127.0.0.1：8000/api/v1/user/userinfo   --->post请求即可
    # 只要post请求过来就会执行create
    def create(self, request, *args, **kwargs):
        # serializer = self.get_serializer(data=request.data)
        # serializer.is_valid(raise_exception=True)
        # self.perform_create(serializer)
        # headers = self.get_success_headers(serializer.data)
        # 序列化要调用它，只要调用serializer.data ，就会走序列化，只要走序列化，会把create返回的user对象 来使用UserRegisterSerializer类做序列化
        # 序列类中得write_only=True
        # return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
        # return APIResponse(msg='注册成功') #不走序列化了，序列类中得write_only 也就不用了
        super().create(request, *args, **kwargs)

    # 写个短信登录注册接口（只需要传手机号和验证码，生成一个默认密码，以短信形式通知用户）

    # 传入手机号码和验证码（这里是验证码必须比较正确才可以），我们测试默认就是8888，然后写个随机密码，存入数据库，再给用户发个短信
    @action(methods=['GET'], detail=False)
    def sms_register(self, request, *args, **kwargs):
        ser = self.get_serializer(data=request.data)
        ser.is_valid(raise_exception=True)
        ser.save()
        return APIResponse(msg='注册成功')

    # 记录三次用户密码修改记录，每次改密码，不能跟之前用过的相同
    def update_password(self, request, *args, **kwargs):
        ser = self.get_serializer(data=request.data)
        ser.is_valid(raise_exception=True)
        ser.save()
        return APIResponse(mag='修改成功')


########################redis的使用#############################
# redis的普通链接
# import redis
# class MyRedisView(APIView):
#     def get(self,request):
#         # 访问一次，redis的a1 +1
#         conn = redis.Redis()   # 没有池的方案，来几个请求，就会创建几个链接
#         conn.incrby('a1')
#         return APIResponse()


##### 使用池
# from utils.redis_pool import POOL
# import redis
# class MyRedisView(APIView):
#     def get(self,request):
#         # 访问一次，redis的a1 +1
#         conn = redis.Redis(connection_pool=POOL)   # 没有池的方案，来几个请求，就会创建几个链接
#         conn.incrby('a1')
#         return APIResponse()

#####使用第三方
# from django_redis import get_redis_connection
#
# class MyRedisView(APIView):
#     def get(self,request):
#         # 访问一次，redis的a1 +1
#         conn = get_redis_connection()   # 从连接池中拿出一个连接
#
#         conn.incrby('a1')
#         conn.set('name','yzk')
#         return APIResponse()


#### 测试缓存的使用
# from django.core.cache import cache
#
#
# class MyRedisView(APIView):
#     def get(self, request):
#         # cache.set('age', 19, 10)  # 现在放在redis中
#         l = [1, 'lqz', [1, 3, 4, 5, 6], '彭于晏']
#         # conn = get_redis_connection()
#         # conn.lpush('l1',[1,2,3])  # 存放json格式字符串。要做序列化
#
#         cache.set('ll1', l)
#
#         return APIResponse()
#
#
# #############################################################################
#
#
# ####测试celery的使用---》前端发送一个get请求，就异步向banner表中插入一条记录
# from celery_task.home_task import add_banner
#
#
# class CeleryView(APIView):
#     def get(self, request):
#         # 同步用,不用了
#         # add_banner()
#         # 异步
#         res = add_banner.delay()
#         print(res)
#
#         return APIResponse(msg='新增banner的任务已经提交了')
#
#
# from celery_task.user_task import sckill_goods
# from celery_task.celery import app
# from celery.result import AsyncResult
#
#
# class SckillView(APIView):
#     def post(self, request, *args, **kwargs):
#         name = request.data.get('name')
#         # 提交秒杀异步任务
#         res = sckill_goods.delay(name)
#         print(res)  # 任务的id
#         return APIResponse(task_id=str(res))
#
#     def get(self, request, *args, **kwargs):
#         task_id = request.GET.get('task_id')
#         print('返回的id',task_id)
#         a = AsyncResult(id=task_id, app=app)
#         if a.successful():  # 正常执行完成
#             result = a.get()  # 任务返回的结果
#             print('判断',result)    # 返回的是True或者False
#             if result:
#                 return APIResponse(code=100, msg='秒杀成功')
#             else:
#                 return APIResponse(code=101, msg='秒杀失败')
#         elif a.status == 'STARTED':
#             print('任务已经开始被执行')
#             return APIResponse(code=103, msg='还在排队')
#         else:
#             return APIResponse(code=102, msg='没成功')

# 111-------------------------------------------------------------------------
# from django.shortcuts import render

# # rest_framework很规范，想导入什么拼写单词即可
# from rest_framework.request import Request
# from rest_framework.response import Response

# from rest_framework.views import APIView
# from django.http import JsonResponse  # 原生的
# from rest_framework.response import Response  # drf提供的
# from .models import Book

# 1  基于APIView+JsonResponse 写接口
# class BookView(APIView):
#     def get(self, request):
#         books = Book.objects.all()
#         book_list = []
#         for book in books:
#             book_list.append({'name': book.name, 'price': book.price, 'publish': book.publish})
#
#         return JsonResponse(book_list, safe=False)

# 基于APIView+Response 写接口
# class BookView(APIView):
#     def get(self, request):
#
#         print(request.GET)
#
#
#         books = Book.objects.all()
#         book_list = []
#         for book in books:
#             book_list.append({'name': book.name, 'price': book.price, 'publish': book.publish})
#
#         return Response(book_list)  # 无论是列表还是字典都可以序列化


# APIView和Response 之前没有用过


#  基于APIView+序列化类+Response 写接口
# from .serializer import BookSerializer
#
#
# class BookView(APIView):
#     def get(self, request):
#         # 只是为了验证之前讲过的
#         print(request.method)
#         print(request._request)
#         print(type(self.request))
#
#         books = Book.objects.all()
#         # 使用序列化类来完成---》得有个序列化类
#         # instance要序列化的数据books queryset对象
#         # many=True 只要是queryset对象要传many=True，如果是单个对象就不用传
#         ser = BookSerializer(instance=books, many=True)
#         return Response(ser.data)  # 无论是列表还是字典都可以序列化
#
#     def post(self, request):
#         # requset.data  # 前端提交的要保存的数据----》校验数据---》存
#         ser = BookSerializer(data=request.data)  # 把前端传入的要保存的数据，给data参数
#         # 校验数据
#         if ser.is_valid():
#             # 保存---->需要自己写，要在序列化类BookSerializer中写----》create方法
#             ser.save()  # 调用ser.save,自动触发咱们写的create，保存起来
#             return Response({'code': 100, 'msg': '新增成功', 'result': ser.data})
#         else:
#             return Response({'code': 101, 'msg': ser.errors})
#
#
# class BookDetailView(APIView):
#     # def get(self, request,pk):
#     def get(self, request, *args, **kwargs):
#         book = Book.objects.filter(pk=kwargs.get('pk')).first()
#         # 序列化
#         ser = BookSerializer(instance=book)
#         return Response(ser.data)
#
#     def put(self, request, pk):
#         book = Book.objects.filter(pk=pk).first()
#         # 反序列化保存 ---借助于序列化类
#         ser = BookSerializer(data=request.data, instance=book)
#         if ser.is_valid():
#             ser.save()  # 由于没有重写update，所以这报错
#             return Response({'code': 100, 'msg': '修改成功', 'result': ser.data})
#         else:
#             return Response({'code': 101, 'msg': ser.errors})
#
#     def delete(self, requset, pk):
#         Book.objects.filter(pk=pk).delete()
#         return Response({'code': 100, 'msg': '删除成功'})

# 111-------------------------------------------------------------------------

###研究---》如果我们要写publish的5个接口---》只需要复制之前的代码，改改一部分，就可以快速写出publish的5个，区别就只在与表模型和序列化类
# class PublishView(APIView):
#     def get(self, request):
#         objs = Publish.objects.all()
#         ser = PublishSerializer(instance=objs, many=True)
#         return Response(ser.data)
#
#     def post(self, request):
#         ser = PublishSerializer(data=request.data)
#         if ser.is_valid():
#             ser.save()
#             # 咱们现在只有ser序列化类的对象，但是咱们想要，新增的对象---》序列化成字典---》大前提，序列化类中的create方法一定要返回新增的对象
#             return Response({'code': 100, 'msg': '新增成功', 'result': ser.data})
#         else:
#             return Response({'code': 101, 'msg': ser.errors})
#
#
# class PublishDetailView(APIView):
#     def get(self, request, pk):
#         books = Publish.objects.filter(pk=pk).first()
#         ser = PublishSerializer(instance=books)
#         return Response(ser.data)
#
#     def put(self, request, pk):
#         books = Publish.objects.filter(pk=pk).first()
#         ser = PublishSerializer(instance=books, data=request.data)
#         if ser.is_valid():
#             ser.save()
#             return Response({'code': 100, 'msg': '修改成功', 'result': ser.data})
#         else:
#             return Response({'code': 101, 'msg': ser.errors})
#
#     def delete(self, request, pk):
#         Publish.objects.filter(pk=pk).delete()
#         return Response({'code': 100, 'msg': '删除成功'})


### 咱们能不能想一种方式，通过继承，少些代码-----》GenericAPIView---》继承了APIView，有很多新的属性和方法
# 以后咱们可以基于这个类，来写5个接口
# 5个接口的效果一样，但是咱们代码 可用性变高了
# GenericAPIView 属性和方法
'''
# 属性
1 queryset:要序列化或反序列化的表模型数据
2 serializer_class：使用的序列化类
3 lookup_field ：查询单条的路由分组分出来的字段名
4 filter_backends：过滤类的配置(了解)
5 pagination_class：分页类的配置(了解)

# 方法
1 get_queryset   ：获取要序列化的对象
2 get_object  ：获取单个对象
3 get_serializer ：获取序列化类  ，跟它差不多的get_serializer_class，一般重写它，不调用它
4 filter_queryset  ：过滤有关系(了解)
'''

from rest_framework.generics import GenericAPIView

# class BookView(GenericAPIView):
#     queryset = Book.objects.all()
#     serializer_class = BookSerializer
#
#     def get(self, request):
#         # objs = self.queryset #这里可以拿到，但是不要这么用，GenericAPIView提供了一个方法，
#         objs = self.get_queryset()  # 好处，可以重写该方法，后期可扩展性高
#         # 取序列化类，不要使用self.serializer_class,而要使用方法
#         ser = self.get_serializer(instance=objs, many=True)  # 后期可以重写get_serializer_class，指定使用哪个序列化类来序列化
#         return Response(ser.data)
#
#     def post(self, request):
#         ser = self.get_serializer(data=request.data)
#         if ser.is_valid():
#             ser.save()
#             # 咱们现在只有ser序列化类的对象，但是咱们想要，新增的对象---》序列化成字典---》大前提，序列化类中的create方法一定要返回新增的对象
#             return Response({'code': 100, 'msg': '新增成功', 'result': ser.data})
#         else:
#             return Response({'code': 101, 'msg': ser.errors})
#
#
# class BookDetailView(GenericAPIView):
#     queryset = Book.objects.all()
#     serializer_class = BookSerializer
#
#     def get(self, request, pk):
#         obj = self.get_object()  # 获取单条
#         ser = self.get_serializer(instance=obj)
#         return Response(ser.data)
#
#     def put(self, request, pk):
#         obj = self.get_object()
#         ser = self.get_serializer(instance=obj, data=request.data)
#         if ser.is_valid():
#             ser.save()
#             return Response({'code': 100, 'msg': '修改成功', 'result': ser.data})
#         else:
#             return Response({'code': 101, 'msg': ser.errors})
#
#     def delete(self, request, pk):
#         self.get_object().delete()
#         return Response({'code': 100, 'msg': '删除成功'})


### 咱们能不能想一种方式，通过继承，少些代码-----》GenericAPIView---》继承了APIView，有很多新的属性和方法
# 以后咱们可以基于这个类，来写5个接口
# 5个接口的效果一样，但是咱们代码 可用性变高了
# GenericAPIView 属性和方法
'''
# 属性
1 queryset:要序列化或反序列化的表模型数据
2 serializer_class：使用的序列化类
3 lookup_field ：查询单条的路由分组分出来的字段名
4 filter_backends：过滤类的配置(了解)
5 pagination_class：分页类的配置(了解)

# 方法
1 get_queryset   ：获取要序列化的对象
2 get_object  ：获取单个对象
3 get_serializer ：获取序列化类  ，跟它差不多的get_serializer_class，一般重写它，不调用它
4 filter_queryset  ：过滤有关系(了解)
'''

from rest_framework.generics import GenericAPIView

# class BookView(GenericAPIView):
#     queryset = Book.objects.all()
#     serializer_class = BookSerializer
#
#     def get(self, request):
#         # objs = self.queryset #这里可以拿到，但是不要这么用，GenericAPIView提供了一个方法，
#         objs = self.get_queryset()  # 好处，可以重写该方法，后期可扩展性高
#         # 取序列化类，不要使用self.serializer_class,而要使用方法
#         ser = self.get_serializer(instance=objs, many=True)  # 后期可以重写get_serializer_class，指定使用哪个序列化类来序列化
#         return Response(ser.data)
#
#     def post(self, request):
#         ser = self.get_serializer(data=request.data)
#         if ser.is_valid():
#             ser.save()
#             # 咱们现在只有ser序列化类的对象，但是咱们想要，新增的对象---》序列化成字典---》大前提，序列化类中的create方法一定要返回新增的对象
#             return Response({'code': 100, 'msg': '新增成功', 'result': ser.data})
#         else:
#             return Response({'code': 101, 'msg': ser.errors})
#
#
# class BookDetailView(GenericAPIView):
#     queryset = Book.objects.all()
#     serializer_class = BookSerializer
#
#     def get(self, request, pk):
#         obj = self.get_object()  # 获取单条
#         ser = self.get_serializer(instance=obj)
#         return Response(ser.data)
#
#     def put(self, request, pk):
#         obj = self.get_object()
#         ser = self.get_serializer(instance=obj, data=request.data)
#         if ser.is_valid():
#             ser.save()
#             return Response({'code': 100, 'msg': '修改成功', 'result': ser.data})
#         else:
#             return Response({'code': 101, 'msg': ser.errors})
#
#     def delete(self, request, pk):
#         self.get_object().delete()
#         return Response({'code': 100, 'msg': '删除成功'})


### 第三册层，如果我们写Pulish的5个接口，继承自GenericAPIView，跟Book的区别只有两个类属性，我们可以再封装
### 封装了5个视图扩展类---》5个接口  get所有，get一个，post新增，put修改，delete删除
# 5个视图扩展类，没有继承APIView及其子类，它不能单独使用，必须配合GenericAPIView一起用才行
# CreateModelMixin:新增，咱们封装---》在CreateModelMixin里面写个post，但是人家不是，人家写了create方法，代码就是post的代码
# DestroyModelMixin：删除     destroy方法
# RetrieveModelMixin：查单条   retrieve方法
# ListModelMixin：查所有      list 方法
# UpdateModelMixin：更新      updata方法
from rest_framework.mixins import CreateModelMixin, UpdateModelMixin, DestroyModelMixin, RetrieveModelMixin, \
    ListModelMixin

# 基于GenericAPIView+5个视图扩展类写接口

# class BookView(GenericAPIView, ListModelMixin, CreateModelMixin):
#     queryset = Book.objects.all()
#     serializer_class = BookSerializer
#
#     def get(self, request):
#         return self.list(request)
#
#     def post(self, request):
#         return self.create(request)
#
#
# class BookDetailView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
#     queryset = Book.objects.all()
#     serializer_class = BookSerializer
#
#     def get(self, request, *args, **kwargs):
#         return self.retrieve(request, *args, **kwargs)
#
#     def put(self, request, *args, **kwargs):
#         return self.update(request, *args, **kwargs)
#
#     def delete(self, request, *args, **kwargs):
#         return self.destroy(request, *args, **kwargs)


### 第四层：基于9个视图子类，编写接口----》5个接口
from rest_framework.generics import ListAPIView, ListCreateAPIView, CreateAPIView, RetrieveAPIView, \
    RetrieveUpdateDestroyAPIView, RetrieveDestroyAPIView, DestroyAPIView, UpdateAPIView

# 查询所有，新增一个
# class BookView(ListAPIView,CreateAPIView)
# class BookView(ListCreateAPIView):  # 查询所有，新增一个
#     queryset = Book.objects.all()
#     serializer_class = BookSerializer
#     # get post通过继承，已经写好了


# 新增一个，修改一个，删除一个
# class BookDetailView(RetrieveUpdateDestroyAPIView):
#     queryset = Book.objects.all()
#     serializer_class = BookSerializer
# get，post，put 在父类中有了


# 后期需求，可能只写某几个，通过继承不同的视图类，实现，比如：5个接口中，只要查询所有和删除1个，如果写？
# class BookView(ListAPIView):  # 查询所有，新增一个
#     queryset = Book.objects.all()
#     serializer_class = BookSerializer
#
#
# # 新增一个，修改一个，删除一个
# class BookDetailView(DestroyAPIView):
#     queryset = Book.objects.all()
#     serializer_class = BookSerializer


### 总结：9个视图子类
'''
1 ListAPIView,CreateAPIView
2 ListAPIView+CreateAPIView  =ListCreateAPIView     给BookView用的
3 RetrieveAPIView,DestroyAPIView,UpdateAPIView
4 RetrieveDestroyAPIView,RetrieveUpdateAPIView       发现Destroy和Update的组合没有，就是没有提供，猜测，必须先查出来，再修改或删除，所以它没有
5 RetrieveUpdateDestroyAPIView  
'''

#### 第5层，咱们发现，写5个接口，还是要写两个视图类，配置两条路由，而两个视图类的代码，又几乎一样
'''
如果两个视图类写成一个，路由 会有两个get，路由路径也不一样
drf写了一个类，ModelViewSet,只要继承它，5个接口都有了，但是路由写法变了
    -重点：一旦继承ModelViewSet，路由写法变了----》变成.as_view({'get': 'list'})
        路由做映射，意思是如果get请求，访问这个地址，就执行视图类的list方法
'''
# from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
#
#
# class BookView(ModelViewSet):  # 查询所有，新增一个
#     queryset = Book.objects.all()
#     serializer_class = BookSerializer


# class BookView(ReadOnlyModelViewSet):  # 只有查询所有和查询单个
#     queryset = Book.objects.all()
#     serializer_class = BookSerializer


###### 研究：路由写法为什么变了？
'''


ModelViewSet=CreateModelMixin+RetrieveModelMixin+UpdateModelMixin+DestroyModelMixin+ListModelMixin+GenericViewSet(没见过)
GenericViewSet=ViewSetMixin【没见过】+GenericAPIView【见过，两个视图基类的】
导致路由写法变了的原因-----》ViewSetMixin 类-----》读--->注释中写了，以后配置路由变成了view = MyViewSet.as_view({'get': 'list', 'post': 'create'})

'''
# from rest_framework.viewsets import ViewSetMixin, ViewSet, GenericViewSet
#
#
# #### 基于ViewSetMixin+APIView写视图类
# # ViewSetMixin放前面路由写法变了
# class TestView(ViewSetMixin, APIView):
#     def login(self, request):
#         return Response('我是登录')


# ViewSetMixin+ APIView=ViewSet
# ViewSetMixin+ GenericAPIView=GenericViewSet

'''
from rest_framework.viewsets下有这几个类
ModelViewSet:5个试图扩展类+ViewSetMixin+GenericAPIView
ReadOnlyModelViewSet：:2个试图扩展类+ViewSetMixin+GenericAPIView   只读的两个
ViewSetMixin：魔法，重新了as_view，只要继承他，以后路由写法变成了映射方法
ViewSet：ViewSetMixin+ APIView  
GenericViewSet：ViewSetMixin+ GenericAPIView
'''

##### 自动生成路由
# from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
#
# class BookView(ModelViewSet):  # 查询所有，新增一个
#     queryset = Book.objects.all()
#     serializer_class = BookSerializer
#


from rest_framework.viewsets import ViewSetMixin
# class BookView(ViewSetMixin,ListCreateAPIView):  # 查询所有，新增一个
#     queryset = Book.objects.all()
#     serializer_class = BookSerializer
#     # list   create


# class BookView(GenericViewSet,ListModelMixin):  # 查询所有
#     queryset = Book.objects.all()
#     serializer_class = BookSerializer


# 发送短信，自动生成路由
from rest_framework.viewsets import ViewSet, GenericViewSet

from rest_framework.decorators import action


# class SendView(ViewSetMixin,APIView)
# class SendView(ViewSet):
#     @action(methods=['POST'], detail=True)
#     def send_sms(self, request,pk):
#         print(pk)
#         # 手机号，从哪去，假设get请求，携带了参数
#         phone = request.query_params.get('phone')
#         print('发送成功,%s' % phone)
#         return Response({'code': 100, 'msg': '发送成功'})


# class SendView(GenericViewSet):
#     queryset = None
#     serializer_class = '序列化类'
#
#     def get_serializer(self, *args, **kwargs):
#         if self.action == 'lqz':
#             return '某个序列化类'
#         else:
#             return '另一个序列化列'
#
#     @action(methods=['GET'], detail=True)
#     def send_sms(self, request, pk):
#         self.get_serializer()
#         print(pk)
#         # 手机号，从哪去，假设get请求，携带了参数
#         phone = request.query_params.get('phone')
#         print('发送成功,%s' % phone)
#         return Response({'code': 100, 'msg': '发送成功'})
#
#     @action(methods=['GET'], detail=True)
#     def lqz(self, request):  # get
#         # 序列化类
#         pass
#
#     @action(methods=['GET'], detail=True)
#     def login(self, request):  # get
#         # 序列化类
#         pass


####  登录接口  自动生成路由+由于登录功能，不用序列化，继承ViewSet
# from .models import User, UserToken
# import uuid


# class UserView(ViewSet):
#     @action(methods=['POST'], detail=False)
#     def login(self, request):
#         username = request.data.get('username')
#         password = request.data.get('password')
#         user = User.objects.filter(username=username, password=password).first()
#         if user:
#             # 用户存在，登录成功
#             # 生成一个随机字符串--uuid
#             token = str(uuid.uuid4())  # 生成一个永不重复的随机字符串
#             # 在userToken表中存储一下：1 从来没有登录过，插入一条，     2 登录过，修改记录
#             # 如果有就修改，如果没有就新增  (if 自己写)
#             # kwargs 传入的东西查找，能找到，使用defaults的更新，否则新增一条
#             UserToken.objects.update_or_create(user=user, defaults={'token': token})
#             return Response({'code': '100', 'msg': '登录成功', 'token': token})
#         else:
#             return Response({'code': '101', 'msg': '用户名或密码错误'})
